Add 02-stage-audiodriver-2michat-v2 pi-gen stage for ReSpeaker V2.0 HAT#41
Add 02-stage-audiodriver-2michat-v2 pi-gen stage for ReSpeaker V2.0 HAT#41genericJE wants to merge 5 commits intoflorian-asche:mainfrom
Conversation
eae3204 to
d9d30a8
Compare
| Type=oneshot | ||
| ExecStart=/usr/bin/configure_audio.sh | ||
| ExecStartPost=/usr/bin/mkdir -p /var/lib/configure_audio | ||
| ExecStartPost=/usr/bin/touch /var/lib/configure_audio/success |
There was a problem hiding this comment.
Services like wireplumber can set volume back to 0%. I suggest that this script runs on every boot.
|
Many thanks for your great work! |
Address review feedback on florian-asche#41: drop the first-boot guard so the mixer tuning runs on every boot. PipeWire / WirePlumber manage ALSA state per session and can reset controls to 0% between reboots, which would leave users stuck silent if the service only ran once. Also make configure_audio.sh surface amixer set failures (previously swallowed by unconditional return 0), so that a broken tuning exits non-zero and the systemd Restart=on-failure path actually retries instead of falsely claiming success and persisting the broken state via alsactl store. Verified with a shim-based test harness (5 cases: happy path, single amixer set failure, missing control, multiple failures, card timeout).
The ReSpeaker 2-Mics Pi HAT V2.0 replaces the WM8960 codec (V1, I2C 0x1a)
with a TLV320AIC3104 codec (I2C 0x18). The mainline kernel already ships
the `snd-soc-tlv320aic3x` driver, so no DKMS module is needed — but a
device-tree overlay and a separate set of mixer defaults are required.
Without these two bits the card either never appears or appears silent.
The new stage mirrors the v1 layout:
- prerun.sh — copy_previous guard, same as v1
- 01-driver/
- 01-packages — build deps only (no dkms, no kernel headers needed)
- 03-run-chroot.sh — clone seeed-linux-dtoverlays, compile
respeaker-2mic-v2_0-overlay.dtbo with dtc, install into /boot/overlays,
enable I2C + dtoverlay=respeaker-2mic-v2_0 in /boot/config.txt
- 02-set-audio-volume/
- 01-run.sh — install script + oneshot unit (same pattern as v1)
- files/configure_audio.sh — TLV320-aware defaults: PCM 85%
(digital pre-DAC, 100% clips on typical JST speakers), HP DAC and
Line DAC to 100% (defaults sit at -23.5 dB), HP and Line output amps
unmuted at 100%, then alsactl store + wpctl sink to 1.0
- files/configure_audio.service — After=sound.target alsa-restore.service,
no dependency on a seeed-voicecard.service (none needed for v2)
The v2 stage is additive; the existing v1 stage is untouched. A build
can pick v1 or v2 by including the matching directory in stage selection.
Follow-up to the initial 02-stage-audiodriver-2michat-v2 commit: - build-all.yml: add build-2michat-v2 and build-2michat-v2-lva jobs and include them in generate-rpi-imager-json.needs. Without this the new stage exists but no image is ever produced. - configure_audio.service: add ConditionPathExists=!/var/lib/configure_audio/success + ExecStartPost touch marker so mixer tuning runs once on first boot and subsequent manual amixer + alsactl store customisations survive reboots. Without the guard every boot reset the mixer to the stage's canned defaults. - configure_audio.sh: drop the wpctl block. The service runs as root under systemd; wpctl requires the PipeWire user session (uid 1000) and the existing `|| true` made it a silent no-op. - 01-driver/01-packages: drop i2c-tools (no runtime hardware detection on v2 — the overlay is fixed) and libasound2-plugins (v2 does not install a custom asound.conf that references resample plugins). - docs/hardware_2mic_v2.md + README.md: add a v2 hardware page and two README rows (base + LVA) mirroring the v1 entries.
Address review feedback on florian-asche#41: drop the first-boot guard so the mixer tuning runs on every boot. PipeWire / WirePlumber manage ALSA state per session and can reset controls to 0% between reboots, which would leave users stuck silent if the service only ran once. Also make configure_audio.sh surface amixer set failures (previously swallowed by unconditional return 0), so that a broken tuning exits non-zero and the systemd Restart=on-failure path actually retries instead of falsely claiming success and persisting the broken state via alsactl store. Verified with a shim-based test harness (5 cases: happy path, single amixer set failure, missing control, multiple failures, card timeout).
55eb107 to
65b9437
Compare
…@1000 dep Match the post-florian-asche#42 pattern already used by 02-stage-audiodriver-2michat-v1: call `wpctl set-volume @DEFAULT_AUDIO_SINK@ 1.0` after the amixer tune so the PipeWire default sink lands at unity, and add `After=/Wants=user@1000.service` + `Environment=XDG_RUNTIME_DIR=/run/user/1000` to the unit so wpctl can reach the user PipeWire socket. Drop the `PCM 85%` amixer set: PipeWire drives PCM as hardware volume passthrough, so wpctl unity immediately overwrites whatever we set PCM to. Verified on satellite-bedroom: `amixer set PCM 50%` then `wpctl set-volume @DEFAULT_AUDIO_SINK@ 1.0` leaves PCM at 100%. Keeping the line made the intent misleading ("85% for headroom") while having zero effect on the final state. The rest of the amixer tuning stays — unlike WM8960 on v1 or the DSP-driven lite board, the TLV320AIC3104 on the V2.0 HAT ships with `HP DAC` at -23.5 dB and `HP` at ~89%. Those stages are downstream of the PipeWire-managed PCM, so wpctl unity on its own still yields a stuck-quiet card.
65b9437 to
9121dd6
Compare
TLV320AIC3104 ships with the input PGA at 27% (16 dB), which is too quiet for reliable microWakeWord triggering on a Pi Zero 2 W at typical speaking distance. Verified on satellite-bedroom: at 27% 'Hey Jarvis' never fires; at 80% (47.5 dB) it does. The output-side tune handled audibility; this handles detectability.
Related follow-up: linger user hardcoded to
|
|
I did changed the audio volume setup again. Can you adjust your changes one more time and test it. If you test input and output and make sure volume is at 100% i merge it. |
Summary
Adds a sibling stage to the existing
02-stage-audiodriver-2michat-v1, targeting the Seeed ReSpeaker 2-Mics Pi HAT V2.0. The V2.0 is a silent hardware revision: it replaces the WM8960 codec (I2C0x1a) with a TLV320AIC3104 (I2C0x18). Today the v1 stage's driver installer silently skips the overlay step on V2.0 hardware, producing a build that boots with no sound card.Related: #22.
What the stage does
01-driver/03-run-chroot.sh— buildsrespeaker-2mic-v2_0-overlay.dtbofrom Seeed-Studio/seeed-linux-dtoverlays withdtc, installs it under/boot/overlays, and enablesdtparam=i2c_arm=on+dtoverlay=respeaker-2mic-v2_0inconfig.txt. No DKMS, no kernel headers —snd-soc-tlv320aic3xis already in the mainline kernel.02-set-audio-volume/files/configure_audio.sh— per-boot mixer tune. The TLV320 ships quiet on both ends: HP DAC at -23.5 dB, HP/Line amps at ~89% and muted on some units, and the capture-side PGA at 27% / 16 dB (too low for microWakeWord detection). Defaults applied:HP DAC→100%,Line DAC→100%HP→100% unmute,Line→100% unmutePGA→80% cap(capture-side input gain)wpctl set-volume @DEFAULT_AUDIO_SINK@ 1.0so HA/LVA volume reaches the hardware stages unattenuated (matches the pattern from fix(audiodriver): remove alsa setup use pipewire volume only #42)02-set-audio-volume/files/configure_audio.service—Type=oneshot,After=sound.target alsa-restore.service wireplumber.service,Requires=user@1000.service. Runs every boot because WirePlumber can reset ALSA state between sessions, so a first-boot-only guard would leave users stuck at the quiet defaults after the next reboot. Runtimeamixertweaks by the user are still possible — they just won't survive a reboot, same as the v1 / Respeaker Lite stages after fix(audiodriver): remove alsa setup use pipewire volume only #42..github/workflows/build-all.yml— addsbuild-2michat-v2andbuild-2michat-v2-lvamatrix jobs, and extendsgenerate-rpi-imager-json.needsso the new images flow through to the RPI Imager JSON.docs/hardware_2mic_v2.md+ README row — hardware page + two README entries mirroring the v1 format.Layout
Mirrors the v1 stage. Gap at
02-run.shis intentional — V2 has no host-side setup (v1 used that slot to install theseeed-voicecard-v2runtime helper that performs hardware detection on every boot; V2 doesn't need it).Test plan
shellcheckclean on all scriptsdebian:bookwormarm64 container with the stage's declared package setbuild-2michat-v2andbuild-2michat-v2-lva) green on the latest commitPiCompose_2MicHat-v2_Linux-Voice-Assistant.img.xzonto a fresh Pi Zero 2 W + V2.0 HAT: clean first-boot, drivers up, audio playback at HA default volume, "Hey Jarvis" wake-word detection working out-of-the-box (no manual mixer adjustment needed)Commit stack
4f4d110— initial stage (overlay build, mixer oneshot, docs, README)dbbf003— self-audit: wire CI jobs, guard mixer service, drop deadwpctlcall, trim01-packagesa119130— run mixer tune every boot and propagateamixerfailures (WirePlumber resets ALSA state between sessions, so a first-boot guard leaves users stuck at quiet defaults after reboot)9121dd6— align with fix(audiodriver): remove alsa setup use pipewire volume only #42: addwpctl set-volume @DEFAULT_AUDIO_SINK@ 1.0+user@1000.servicedependency so the user-scoped pipewire socket exists when the service runs138a088— boost capture PGA from 27% (16 dB) to 80% (47.5 dB) for reliable microWakeWord detection; verified on satellite-bedroom that 27% produces zero wake-word triggers at normal speaking distance and 80% fixes it